package org.zjvis.datascience.common.util;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.HttpClientConfig;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.zjvis.datascience.common.constant.UserConstant;
import org.zjvis.datascience.common.dto.sms.SmsDTO;
import org.zjvis.datascience.common.exception.BaseErrorCode;
import org.zjvis.datascience.common.exception.DataScienceException;

import java.security.SecureRandom;

/**
 * @description : 阿里云短信接口配置类
 * @date 2021-12-14
 */
@Component
public class AliyunSmsUtil {

    @Autowired
    private RedisUtil redisUtil;

    @Value("${aliyun.access-key-id}")
    private String ACCESS_KEY_ID;

    @Value("${aliyun.access-key-secret}")
    private String ACCESS_KEY_SECRET;

    /* 短信API产品名称（短信产品名固定，无需修改） */
    private static final String product = "Dysmsapi";

    /* 短信API产品域名，接口地址固定，无需修改 */
    private static final String domain = "dysmsapi.aliyuncs.com";

    private static final String SMS_SIGNATURE = "之江天枢";
    private static final String SMS_REGISTER_TEMPLATE = "SMS_223178552";
    private static final String SMS_MODIFY_TEMPLATE = "SMS_223178553";
    private static final String SMS_BIND_TEMPLATE = "SMS_229638627";
    private static final String SMS_LOGIN_TEMPLATE = "SMS_229613715";
    private static final int DEFAULT_CONNECT_TIMEOUT = 3000;
    private static final int DEFAULT_READ_TIMEOUT = 3000;
    private IAcsClient ACS_CLIENT = null;

    /**
     * 初始化短信发送客户端
     */
    private void init() {
        /* 初始化acsClient,暂不支持region化 */
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        HttpClientConfig httpClientConfig = HttpClientConfig.getDefault();
        httpClientConfig.setConnectionTimeoutMillis(DEFAULT_CONNECT_TIMEOUT);
        httpClientConfig.setReadTimeoutMillis(DEFAULT_READ_TIMEOUT);
        profile.setHttpClientConfig(httpClientConfig);
        DefaultProfile.addEndpoint("cn-hangzhou", product, domain);
        ACS_CLIENT = new DefaultAcsClient(profile);
    }

    /* 短信发送 */
    public boolean sendSms(String phone, String type) throws ClientException {
        if (ACS_CLIENT == null) {
            init();
        }
        /* 组装请求对象-具体描述见控制台-文档部分内容 */
        SendSmsRequest request = new SendSmsRequest();
        /* 必填:待发送手机号 */
        request.setPhoneNumbers(phone);
        /* 必填:短信签名-可在短信控制台中找到 */
        request.setSignName(SMS_SIGNATURE);

        String key = null;
        /* 必填:短信模板code-可在短信控制台中找到 */
        switch (type) {
            case UserConstant.TYPE_OF_REGISTER:
                request.setTemplateCode(SMS_REGISTER_TEMPLATE);
                key = UserConstant.REGISTER_PREFIX + phone;
                break;
            case UserConstant.TYPE_OF_MODIFY:
                request.setTemplateCode(SMS_MODIFY_TEMPLATE);
                key = UserConstant.MODIFY_PREFIX + phone;
                break;
            case UserConstant.TYPE_OF_BIND:
                request.setTemplateCode(SMS_BIND_TEMPLATE);
                key = UserConstant.BIND_PREFIX + phone;
                break;
            case UserConstant.TYPE_OF_LOGIN:
                request.setTemplateCode(SMS_LOGIN_TEMPLATE);
                key = UserConstant.LOGIN_PREFIX + phone;
                break;
        }

        String code = getMsgCode();
        request.setTemplateParam("{\"code\":\"" + code + "\"}");

        // hint 此处可能会抛出异常，注意catch
        SendSmsResponse sendSmsResponse = ACS_CLIENT.getAcsResponse(request);
        if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
            SmsDTO value = (SmsDTO) redisUtil.get(key);
            value.setVerifyCode(code);
            long expire = redisUtil.getExpire(key);
            redisUtil.set(key, value, expire);
            return true;
        } else {
            throw new DataScienceException(BaseErrorCode.USER_SEND_MESSAGE_ERROR);
        }
    }

    /**
     * 生成验证码
     */
    private static String getMsgCode() {
        int n = 6;
        StringBuilder code = new StringBuilder();
        SecureRandom ran = new SecureRandom();
        for (int i = 0; i < n; i++) {
            code.append(Integer.valueOf(ran.nextInt(10)).toString());
        }
        return code.toString();
    }
}